home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
gnulib
/
libsrc98.zoo
/
dirent.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-05
|
5KB
|
270 lines
/* POSIX compatible directory access routines for TOS */
/* written by Eric R. Smith and placed in the public domain */
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <types.h>
#include <stat.h>
#include <errno.h>
#include <dirent.h>
#include <osbind.h>
#include <unistd.h>
#include "lib.h"
#include "symdir.h"
#ifndef _COMPILER_H
#include <compiler.h>
#endif
static char *shadowed __PROTO((const char *name, SYMDIR *dir));
ino_t __inode; /* in stat.c */
DIR *__opendir_chain; /* ditto */
static
char *shadowed(name, dir)
const char *name;
SYMDIR *dir;
{
SYMENTRY *ent;
if (!dir)
return (char *)0;
ent = dir->s_dir;
while (ent) {
if (!strcmp(name, ent->linkto) && (ent->flags & SD_AUTO))
return ent->linkname;
ent = ent->next;
}
return (char *)0;
}
DIR *opendir(_dirname)
const char *_dirname;
{
char dirname[FILENAME_MAX];
char tmpnam[_LIB_NAME_MAX];
char *t;
DIR *dd;
struct dirent *d, *x, **last;
SYMENTRY *lent;
SYMDIR *ldir;
long r;
short i = 0;
struct _dta mydta, *olddta;
_unx2dos(_dirname, dirname);
#if 0
/* we should maybe check to see if we're opening a directory */
/* this code doesn't work, though -- Fattrib is dumb */
if (dirname[0] && (dirname[1] == ':') && !dirname[2]) {
/* nothing to do */
} else {
r = Fattrib(dirname, 0, FA_DIR|FA_HIDDEN|FA_SYSTEM);
if (r < 0) {
errno = -r;
return NULL;
}
else if (!(r & FA_DIR)) {
errno = EPATH;
return NULL;
}
}
#endif
if (!(dd = malloc((size_t)sizeof(DIR)))) {
errno = ENOMEM;
return NULL;
}
olddta = (struct _dta *)Fgetdta();
Fsetdta(&mydta);
d = x = NULL;
last = &d;
dd->D_path = strdup(dirname);
/* check for symbolic links in the directory */
ldir = _read_symdir(dirname);
if (!ldir)
goto skip_symlinks;
lent = ldir->s_dir;
while (lent) {
x = malloc((size_t)(__DIRENTSIZ(strlen(lent->linkname))));
if (!x) {
errno = ENOMEM;
free(dd->D_path);
free(dd);
while(d) {
x = d->d_next;
free(d);
d = x;
}
_free_symdir(ldir);
Fsetdta(olddta); /* reset dta ++jrb */
return NULL;
}
strcpy(x->d_name, lent->linkname);
x->d_reclen = x->d_size = strlen(x->d_name);
x->d_ino = ++__inode;
x->d_off = i++;
x->d_next = NULL;
x->d_date = x->d_time = 0;
x->d_attribute = 0xff; /* mark symbolic link */
*last = x;
last = &x->d_next;
lent = lent->next;
}
/* OK, so much for the symbolic links. Now for the real directories */
skip_symlinks:
strcat(dirname, "\\*.*");
if ((r = Fsfirst(dirname, FA_SYSTEM|FA_HIDDEN|FA_DIR)) != 0) {
/* report an error unless dirname is a root directory */
/* (all other valid directories have '.' and '..' in them */
if (!*dirname || strcmp(dirname+1, "\\*.*")) {
errno = -r;
while (d) {
x = d->d_next;
free(d);
d = x;
}
free(dd->D_path);
free(dd);
dd = NULL;
}
} else { /* Fsfirst worked OK */
do {
_dos2unx(mydta.dta_name, tmpnam);
/* skip the symbolic directory itself if we're supposed to */
if (_lHIDE && _lOK && !strcmp(_lDIR, tmpnam))
continue;
/* check for files being hidden by auto symlinks */
if (_lAUTO && (t = shadowed(tmpnam, ldir))) {
for (x = d; x; x = x->d_next)
if (!strcmp(x->d_name, t))
break;
assert(x != 0);
/* put the real file's info in the structure */
goto tos_fill;
}
x = malloc((size_t)(__DIRENTSIZ(strlen(tmpnam))));
if (!x) {
errno = ENOMEM;
while (d) {
x = d->d_next;
free(d);
d = x;
}
free(dd->D_path);
free(dd);
dd = NULL;
break;
}
strcpy(x->d_name, tmpnam);
x->d_ino = ++__inode; /* make sure no two are equal */
x->d_off = i++;
/* I don't know what d_reclen means on Unix, but for TOS we might as well
stuff the string length in here (so sys/dir.h can be more like BSD) */
x->d_reclen = strlen(x->d_name);
x->d_next = NULL;
*last = x;
last = &x->d_next;
tos_fill:
/* fill in TOS specific stuff so stat can find it later */
x->d_time = mydta.dta_time;
x->d_date = mydta.dta_date;
x->d_attribute = mydta.dta_attribute;
x->d_size = mydta.dta_size;
} while (!Fsnext());
}
Fsetdta(olddta);
if (dd) {
dd->D_list = dd->D_curpos = d;
dd->D_nxtdir = __opendir_chain;
__opendir_chain = dd;
}
_free_symdir(ldir);
return dd;
}
struct dirent *readdir(dirp)
DIR *dirp;
{
struct dirent *x;
if (!dirp) return NULL;
x = dirp->D_curpos;
if (x) dirp->D_curpos = x->d_next;
return x;
}
off_t telldir(dirp)
DIR *dirp;
{
struct dirent *x = dirp->D_curpos;
if (x)
return x->d_off;
else
return -1;
}
void seekdir(dirp, loc)
DIR *dirp;
off_t loc;
{
struct dirent *x;
x = dirp->D_list;
while (x && x->d_off != loc)
x = x->d_next;
dirp->D_curpos = x;
}
void rewinddir(dirp)
DIR *dirp;
{
dirp->D_curpos = dirp->D_list;
}
int closedir(dirp)
DIR *dirp;
{
struct dirent *x, *oldx;
DIR **old, *nxt;
if (!dirp) return -1;
if (dirp->D_path)
free(dirp->D_path);
for (x = dirp->D_list; x; ) {
oldx = x;
x = x->d_next;
free(oldx);
}
/* unlink from __opendir_chain */
old = &__opendir_chain;
nxt = *old;
while (nxt) {
if (nxt == dirp) {
*old = nxt->D_nxtdir;
nxt->D_nxtdir = 0;
break;
}
old = &nxt->D_nxtdir;
nxt = *old;
}
free(dirp);
return 0;
}